#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <sstream>
#include <cstring>
#include <jsoncpp/json/json.h>

using namespace std;

//========================================================================================================
// namespace Src_Json_API
// {
//     // Json数据对象类
//     class Json::Value
//     {
//         Value &operator=(const Value &other);      // Value重载了[]和=，因此所有的赋值和获取数据都可以通过
//         Value &operator[](const std::string &key); // 简单的方式完成 val["姓名"] = "小明";
//         Value &operator[](const char *key);
//         Value removeMember(const char *key);             // 移除元素
//         const Value &operator[](ArrayIndex index) const; // val["成绩"][0]
//         Value &append(const Value &value);               // 添加数组元素val["成绩"].append(88);
//         ArrayIndex size() const;                         // 获取数组元素个数 val["成绩"].size();
//         std::string asString() const;                    // 转string string name = val["name"].asString();
//         const char *asCString() const;                   // 转char* char *name = val["name"].asCString();
//         Int asInt() const;                               // 转int int age = val["age"].asInt();
//         float asFloat() const;                           // 转float
//         bool asBool() const;                             // 转 bool
//     };

//     // json序列化类，低版本用这个更简单
//     class JSON_API Writer
//     {
//         virtual std::string write(const Value &root) = 0;
//     };
//     class JSON_API FastWriter : public Writer
//     {
//         virtual std::string write(const Value &root);
//     };
//     class JSON_API StyledWriter : public Writer
//     {
//         virtual std::string write(const Value &root);
//     };

//     // json序列化类，高版本推荐，如果用低版本的接口可能会有警告
//     class JSON_API StreamWriter
//     {
//         virtual int write(Value const &root, std::ostream *sout) = 0;
//     };
//     class JSON_API StreamWriterBuilder : public StreamWriter::Factory
//     {
//         virtual StreamWriter *newStreamWriter() const;
//     };
//     //========================================================================================================

//     // json反序列化类，低版本用起来更简单
//     class JSON_API Reader
//     {
//         bool parse(const std::string &document, Value &root, bool collectComments = true);
//     };
//     // json反序列化类，高版本更推荐
//     class JSON_API CharReader
//     {
//         virtual bool parse(char const *beginDoc, char const *endDoc,
//                            Value *root, std::string *errs) = 0;
//     };
//     class JSON_API CharReaderBuilder : public CharReader::Factory
//     {
//         virtual CharReader *newCharReader() const;
//     };

// }
//========================================================================================================

int main()
{
    string name("张三");
    int age = 20;
    vector<double> score{78.5, 56.5, 74.5};

    Json::Value js;
    js["name"] = name.c_str();
    js["age"] = age;
    for (auto &val : score)
        js["score"].append(val);

    // 1. 序列化 -- 结构化数据(Json::Value存储的数据)按特定的格式转化成字符串
    Json::StreamWriterBuilder swb;
    unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter()); // StreamWriter不能直接定义，write接口是虚函数
    std::stringstream ss;
    int ret = sw->write(js, &ss); // write第二次参数为输出型，转化成功自动填充到这里
    if (ret != 0)
    {
        std::cout << "write failed!\n";
        return -1;
    }
    std::cout << ss.str() << std::endl;

    // 2.反序列化 -- 字符串转化成Json::Value结构化数据
    Json::CharReaderBuilder crb;
    string JsonData(ss.str());
    Json::Value root;
    string errs;
    unique_ptr<Json::CharReader> pcrb(crb.newCharReader());
    bool IsSucess = pcrb->parse(JsonData.c_str(), JsonData.c_str() + strlen(JsonData.c_str()), &root, &errs);
    if (IsSucess == false)
    {
        cout << "parse error: " << errs << endl;
    }
    int size = root["score"].size();
    for (int i = 0; i < size; ++i)
        cout << "name: " << root["name"].asString() << "  age: " << root["age"].asInt()
             << "  score: " << root["score"][i].asDouble() << endl;
    return 0;
}
